package ashbyutils.email;

import java.util.ArrayList;
import java.util.Date;
import java.util.Properties;

import javax.mail.Message;
import javax.mail.MessagingException;
import javax.mail.NoSuchProviderException;
import javax.mail.Session;
import javax.mail.Transport;
import javax.mail.internet.AddressException;
import javax.mail.internet.InternetAddress;
import javax.mail.internet.MimeMessage;

/**
 * An email class. Works just like a regular text email... set its' fields (to,
 * from, etc) and call send().
 * 
 * @author Greg.Ashby
 * @date 17-Aug-2004
 */
public class Email {

	public final static String PROTOCOL = "smtp";
	//public final static String HOST = "shawmail";
	public final static String HOST = "localhost";
	public final static String PROTOCOL_KEY = "mail.transport.protocol";
	public final static String HOST_KEY = "mail.host";
	public final static String HOST_PROTOCOL_KEY = "mail." + PROTOCOL + ".key";
	public final static String DEFAULT_CHARACTER_SET = "ISO-8859-1";

	static {
		Properties systemProperties = System.getProperties();
		systemProperties.put(PROTOCOL_KEY, PROTOCOL);
		systemProperties.put(HOST_PROTOCOL_KEY, HOST);
		systemProperties.put(HOST_KEY, HOST);
	};

	/**
	 * @return
	 */
	public static Email createInstance() {
		return new Email(Session.getInstance(System.getProperties(), null), DEFAULT_CHARACTER_SET);
	}

	private final Session aMailSession;
	private final String aCharacterSet;
	private boolean isHtml = false;

	/**
	 * Comma delimited email addresses
	 */
	private String to = null;

	/**
	 * Comma delimited email addresses
	 */
	private String cc = null;

	/**
	 * Comma delimited email addresses
	 */
	private String bcc = null;

	private String from = null;
	private String subject = null;
	private String body = null;

	private ArrayList fileNames = new ArrayList();

	/**
	 * @param aSession
	 * @param aCharacterSet
	 */
	protected Email(Session aSession, String aCharacterSet) {
		aMailSession = aSession;
		this.aCharacterSet = aCharacterSet;
	}

	/**
	 * @return
	 */
	public String getBody() {
		return body;
	}

	/**
	 * @return
	 */
	public String getCc() {
		return cc;
	}

	/**
	 * @return
	 */
	public String getBcc() {
		return bcc;
	}

	/**
	 * @return
	 */
	public String getFrom() {
		return from;
	}

	/**
	 * @return
	 */
	public String getSubject() {
		return subject;
	}

	/**
	 * @return
	 */
	public String getTo() {
		return to;
	}

	/**
	 * @param string
	 */
	public void setBody(String string) {
		body = string;
	}

	/**
	 * @param string
	 */
	public void setCc(String string) {
		cc = string;
	}

	/**
	 * @param string
	 */
	public void setBcc(String string) {
		bcc = string;
	}

	/**
	 * @param string
	 */
	public void setFrom(String string) {
		from = string;
	}

	/**
	 * @param string
	 */
	public void setSubject(String string) {
		subject = string;
	}

	/**
	 * @param string
	 */
	public void setTo(String string) {
		to = string;
	}

	/**
	 * performs a very rudimentary validation check to make sure all required
	 * fields are set.
	 * 
	 * @throws IllegalStateException
	 */
	public void validate() throws IllegalStateException {
		if ((getTo() == null && getCc() == null) || getFrom() == null || getBody() == null) {
			throw new IllegalStateException("A required email field (body, from or either to or cc) is not set");
		}
	}

	/**
	 * @throws AddressException
	 * @throws MessagingException
	 */
	public void send() throws AddressException, MessagingException {

		validate();
		MimeMessage message = prepareMessage();
		sendIt(message);

	}

	/**
	 * @param message
	 * @throws NoSuchProviderException
	 * @throws MessagingException
	 */
	protected void sendIt(Message message) throws NoSuchProviderException, MessagingException {
		Transport transport = getMailSession().getTransport();
		transport.connect();
		Transport.send(message);
		transport.close();
	}

	/**
	 * @return
	 * @throws AddressException
	 * @throws MessagingException
	 * @throws AddressException
	 */
	protected MimeMessage prepareMessage() throws AddressException, MessagingException {

		MimeMessage message = new MimeMessage(getMailSession());

		if (getTo() != null) {
			InternetAddress[] toAddresses = InternetAddress.parse(getTo(), false);
			message.setRecipients(Message.RecipientType.TO, toAddresses);
		}

		InternetAddress fromAddress = InternetAddress.parse(getFrom(), false)[0];
		message.setFrom(fromAddress);

		if (getCc() != null) {
			InternetAddress[] ccAddresses = InternetAddress.parse(getCc(), false);
			message.setRecipients(Message.RecipientType.CC, ccAddresses);
		}

		if (getBcc() != null) {
			InternetAddress[] ccAddresses = InternetAddress.parse(getBcc(), false);
			message.setRecipients(Message.RecipientType.BCC, ccAddresses);
		}

		if (subject != null) {
			message.setSubject(getSubject(), getCharacterSet());
		}

		if (isHtml) {
			message.setContent(getBody(), "text/html");
		} else {
			message.setText(getBody(), getCharacterSet());
		}

		message.setSentDate(new Date());
		message.setHeader("Content-Transfer-Encoding", "quoted-printable");

		return message;
	}

	/**
	 * @return
	 */
	protected Session getMailSession() {
		return aMailSession;
	}

	/**
	 * @return
	 */
	protected String getCharacterSet() {
		return aCharacterSet;
	}

	/**
	 * @return
	 */
	public boolean isHtml() {
		return isHtml;
	}

	/**
	 * If this is set to true, the email will be sent with html markup,
	 * otherwise, just as plain text.
	 * 
	 * @param b
	 */
	public void setHtml(boolean b) {
		isHtml = b;
	}

}